﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibraryONTrack.dto;
using LibraryONTrack.dao;
using System.Windows.Forms;

namespace LibraryONTrack.BAL
{
	[Serializable]
	public class OverdueBookManagerException : Exception
	{
		public OverdueBookManagerException() { }
		public OverdueBookManagerException(string message) : base(message) { }
		public OverdueBookManagerException(string message, Exception inner) : base(message, inner) { }
		protected OverdueBookManagerException(
		System.Runtime.Serialization.SerializationInfo info,
		System.Runtime.Serialization.StreamingContext context)
			: base(info, context) { }
	}

	[Serializable]
	public class AssignedToAnotherUserOverdueBookManagerException : Exception
	{
		public Student Borrower { get; set; }
		public AssignedToAnotherUserOverdueBookManagerException() { }
		public AssignedToAnotherUserOverdueBookManagerException(Student borrower) : base() { Borrower = borrower; }
		public AssignedToAnotherUserOverdueBookManagerException(string message) : base(message) { }
		public AssignedToAnotherUserOverdueBookManagerException(string message, Exception inner) : base(message, inner) { }
		public AssignedToAnotherUserOverdueBookManagerException(string message, Student borrower, Exception inner) : base(message, inner) { Borrower = borrower;  }
		protected AssignedToAnotherUserOverdueBookManagerException(
		System.Runtime.Serialization.SerializationInfo info,
		System.Runtime.Serialization.StreamingContext context)
			: base(info, context) { }
	}



	public class OverdueBookManager
	{
		public BookManager BookManager { get; private set; }
		public RosterManager RosterManager { get; private set; }
        OverdueBookDAO overdueBookDAO;
        List<OverdueBook> overdueBookList;

		public OverdueBookManager()
		{
			BookManager = new BookManager();
			RosterManager = new RosterManager();
		}

        public void AdvanceNotice()
        {
            overdueBookDAO = new OverdueBookDAO();
            overdueBookList = overdueBookDAO.GetAllOverdueBooks();

            foreach (OverdueBook book in overdueBookList)
            {
                if (book.NoticeCount < 4)
                {
                    book.NoticeCount = book.NoticeCount + 1;
                    overdueBookDAO.Update(book);
                }
            }
            MessageBox.Show("Notices Advanced Successfully!");
        }
        public void RetractNotice()
        {
            overdueBookDAO = new OverdueBookDAO();
            overdueBookList = overdueBookDAO.GetAllOverdueBooks();
            foreach (OverdueBook book in overdueBookList)
            {
                if (book.NoticeCount > 0)
                {
                    book.NoticeCount = book.NoticeCount - 1;
                    overdueBookDAO.Update(book);
                }
            }
            MessageBox.Show("Notices Retracted Successfully!");
        }
        //Set still_overdue_ind to False
        public void SetStillOverdueInd()
        {
            overdueBookDAO = new OverdueBookDAO();
            overdueBookList = overdueBookDAO.GetAllOverdueBooks();
            //Set still_overdue_ind = 0 for all of the remaining records
            foreach (OverdueBook book in overdueBookList)
            {
                if (book.StillOverdue)
                {
                    book.StillOverdue = false;
                    //Update all books
                    overdueBookDAO.Update(book);
                }
            }
        }

        public void PurgeReturnedBooks()
        {
            //Delete all of the records in overdue_books where
            //still_overdue_ind = 0
            overdueBookDAO = new OverdueBookDAO();
            overdueBookList = overdueBookDAO.GetAllOverdueBooks();

            foreach (OverdueBook book in overdueBookList)
            {
                if (!book.StillOverdue)
                {
                    overdueBookDAO.Delete(book.Book.BookId, book.Borrower.Id);
                }
            }
        }

		public void AddOverdueBook(Student borrower, Book book, Student takeFrom=null)
		{
			OverdueBookDAO dao = new OverdueBookDAO();
			
			// Get student's teacher. We don't take as an argument to enforce the roster
			Teacher teacher = new TeacherDAO().GetById(borrower.TeacherId);
			
			// See if book is already checked out and if so, to this student
			OverdueBook overdueBook = dao.GetOverdueBook(book.BookId);
			if (overdueBook != null)
			{
				// Book is currently marked as overdue. See if its for this borrower
				if (overdueBook.Borrower.Id == borrower.Id)
				{
					// Same borrower, update that its still overdue (unless already set)
					if (!overdueBook.StillOverdue)
					{
						// Flag that book is still overdue
						overdueBook.StillOverdue = true;
						dao.Update(overdueBook);
					}
				}
				else
				{
					// Are we allowed to forcibly move to the new borrower?
					if (takeFrom != null)
					{
						// Yes. Delete the existing overdue assignment
						dao.Delete(overdueBook.Book.BookId, takeFrom.Id);

						// and reassign to new borrower
						dao.Insert(new OverdueBook(book, borrower, teacher, 0));					
					}
					else
					{
						throw new AssignedToAnotherUserOverdueBookManagerException(overdueBook.Borrower);
					}
				}
			}
			else
			{
				// Book is not currently flagged as overdue. Setup
				dao.Insert(new OverdueBook(book, borrower, teacher, 0));
			}			
		}
	}
}
